{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第2周 Python基础（一）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.数据类型\n",
    "## 2.列表、元组、字典、集合\n",
    "## 3.运算符"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 教学目标：掌握Python数据类型\n",
    "### 教学重点：掌握列表、元组、字典、集合的区别\n",
    "### 教学难点：列表、字典、集合的常用方法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1.数据类型\n",
    "  什么是变量？——可以理解为超市购物车，用来存储商品（数据），再对这些数据进行运算。变量的类型和值在赋值的那一刻被初始化。变量的赋值是通过等号来表示的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_one = 100     #  num_one 就是一个变量，存储的是数据100\n",
    "num_two = 87      #  num_two 也是一个变量，存储的是数据87\n",
    "result = num_one + num_two   #  result 又是一个变量，存储是num_one + num_two之和"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果使用变量存储数据时，为了更充分利用内存空间，可以为变量指定不同的数据类型。Python中常见的数据类型有：\n",
    "数字类型(number)：整型(int)、浮点型（float）、复数（complex）；\n",
    "布尔类型（bool）；\n",
    "字符串类型（str）；\n",
    "列表类型（list）；\n",
    "元组类型（tuple）；\n",
    "字典类型（dict）；\n",
    "集合类型（set）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （1）数字类型--整型（int）、浮点型（float）、复数（complex）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "#  88  0b0101  -239  0x80    整数除常见的十进制数以外，还有以0b开头的二进制数、0x开头的十六进制数、0开头的八进制数……\n",
    "#  3.14\n",
    "#  3+4j"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "print(math.factorial(5))                 # 计算5的阶乘\n",
    "print(0.4-0.3 == 0.1)                   # 浮点数之间尽量避免直接比较大小\n",
    "print(math.isclose(0.4-0.3, 0.1))       # 测试两个浮点数是否足够接近"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c = 3+4j                                # Python内置支持复数及其运算\n",
    "print(c+c)                              # 复数相加\n",
    "print(c**2)                             # 幂运算\n",
    "print(c.real)                           # 查看复数的实部\n",
    "print(c.imag)                           # 查看复数的虚部\n",
    "print(3+4j.imag)                        # 相当于3+(4j).imag\n",
    "print(c.conjugate())                    # 查看共轭复数\n",
    "print(abs(c))                           # 计算复数的模"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （2）字符串（str）\n",
    "--- 使用单引号、双引号、三引号作为定界符，不同定界符之间可以互相嵌套；前面加字母r或R表示原始字符串，任何字符都不进行转义。字符串具有索引规则，第1个字符的索引为0，以此类推。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "string_one = 'python'\n",
    "string_two = \"python\"\n",
    "string_three = '''python'''\n",
    "string_four = '''学习就怕难'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "r'C:\\windows\\notepad.exe'   # 如果字符串中含有反斜线“\\”,建议在字符串前面加上字母r，表示原始字符串，字符“\\”不再表示转义"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "--- Python默认使用utf8编码格式，全面支持中文字符，在使用内置函数len()统计字符串长度时，一个汉字和一个英文字母都作为一个字符对待。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "text = '''Beautiful is better than ugly.\n",
    "Explicit is better than implicit.\n",
    "Simple is better than complex.\n",
    "Complex is better than complicated.\n",
    "Flat is better than nested.\n",
    "Sparse is better than dense.\n",
    "Readability counts.'''\n",
    "print(len(text))                 # 字符串长度，即所有字符的数量\n",
    "print(text.count('is'))          # 字符串中单词is出现的次数\n",
    "print('beautiful' in text)       # 测试字符串中是否包含单词beautiful\n",
    "print('='*20)                    # 字符串重复\n",
    "print('Good '+'Morning')         # 字符串连接"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "--- 字符串属于不可变对象，所有方法都是返回处理后的字符串或字节串，不对原字符串进行任何修改。\n",
    "字符串常用方法有："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "encode()与 decode()方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# encode()方法   使用指定的编码格式把字符串编码为字节串\n",
    "# decode()方法   使用指定的编码格式把字节串解码为字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bookName = '《Python可以这样学》'\n",
    "print(bookName.encode())    # 默认使用utf8码编码格式\n",
    "print(bookName.encode('gbk'))\n",
    "print(bookName.encode('gbk').decode('gbk'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "format()方法----用于把数据格式化为特定格式的字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用{index/name:fmt}作为占位符，其中index表示参数序号，或者用name表示参数名称，fmt表示格式和相应的修饰。\n",
    "# 常用的格式有：b（二进制）、c（把整数转换成Unicode字符）、d（十进制格式）、o（八进制格式）\n",
    "             #  x（小写十六进制格式）、X（大写十六进制格式）、e/E(科学计数法格式)\n",
    "             #  f/F(固定长度的浮点数格式)、%（set用固定长度浮点数显示百分数）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 0表示format()方法的参数下标，对应于第一个参数\n",
    "# .4f表示格式化为实数，保留4位小数\n",
    "print('{0:.4f}'.format(10/3))   \n",
    "print('{0:.2%}'.format(1/3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 格式化为百分数字符串，总宽度为10，保留2位小数，>表示右对齐\n",
    "print('{0:>10.2%}'.format(1/3)) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 逗号表示在数字字符串中插入逗号作为千分符，#x表示格式化为十六进制数\n",
    "print(\"{0:,} in hex is: {0:#x}, in oct is {0:#o}\".format(5555555)) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 可以先格式化下标为1的参数，再格式化下标为0的参数\n",
    "# o表示八进制数，但不带前面的引导符0o\n",
    "print(\"{1} in hex is: {1:#x}, {0} in oct is {0:o}\".format(6666, 66666))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# _表示在数字中插入下画线作为千分符\n",
    "print('{0:_},{0:#_x}'.format(10000000))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "index()、rindex()、count()方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# index()   返回一个字符串在当前字符中首次出现的位置，如果当前字符串中不存在此字符串，则抛出异常\n",
    "# rindex()  返回一个字符串在当前字符中最后一次出现的位置，如果当前字符串中不存在此字符串，则抛出异常\n",
    "# count()   返回一个字符串在当前字符串中出现的次数，如果当前字符串中不存在此字符串，则返回0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "text = '处处飞花飞处处；声声笑语笑声声。'\n",
    "print(text.rindex('处'))\n",
    "print(text.index('声'))\n",
    "print(text.count('处'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "replace()、maketrans()、translate()方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# replace()  用于替换字符串，相当于Word中“全部替换”功能，返回一个新字符串，并不修改原字符串\n",
    "text = \"Python是一门非常棒的编程语言。\"\n",
    "# replace()方法返回替换后的新字符串，可以直接再次调用replace()方法\n",
    "print(text.replace('棒','优雅').replace('编程', '程序设计'))\n",
    "print(text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# maketrans() 用来生成字符映射表\n",
    "# translate() 用来根据映射表中定义的对应关系转换字符串并替换其中的字符\n",
    "table = ''.maketrans('0123456789', '零一二三四伍陆柒捌玖')\n",
    "print('Tel:30647359'.translate(table))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "split()、rsplit()、join()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# split()   使用指定的字符串作为分隔符对原字符串从左向右进行分割\n",
    "# rsplit()  使用指定的字符串作为分隔符对原字符串从右向左进行分割\n",
    "# join()    使用指定的字符串作为连接符对可迭代对象中的若干字符串进行连接"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "text = 'Beautiful is better than ugly.'\n",
    "print(text.split())                     # 使用空白字符进行分隔\n",
    "print(text.split(maxsplit=1))           # 最多分隔一次\n",
    "print(text.rsplit(maxsplit=2))          # 最多分隔两次\n",
    "print('1,2,3,4'.split(','))             # 使用逗号作为分隔符\n",
    "print(','.join(['1', '2', '3', '4']))   # 使用逗号作为连接符\n",
    "print(':'.join(map(str, range(1, 5))))  # 使用冒号作为连接符\n",
    "print(''.join(map(str, range(1, 5))))   # 直接连接，不插入任何连接符"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "strip()、rstrip()、lstrip()方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# strip()   用来删除字符串两侧空白字符或指定的字符\n",
    "# rstrip()  用来删除字符串右侧侧空白字符或指定的字符\n",
    "# lstrip()  用来删除字符串左侧侧空白字符或指定的字符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "text = '   ======test===#####   '\n",
    "print(text.strip())          # 删除两侧的空白字符\n",
    "print(text.strip('=# '))     # 删除两侧的=、#和空格"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*列表类型（list）  所有元素放在一对方括号中，元素之间使用逗号分隔，其中的元素可以是任意类型。例：[79, 89, 99] \n",
    "['a', {3}, (1,2), ['c', 2], {65:'A'}]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*元组类型（tuple）所有元素放在一对圆括号中，元素之间使用逗号分隔，元组中只有一个元素时后面的逗号不能省略。例：(1, 0, 0)、(0,)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*字典类型（dict）所有元素放在一对大括号中，元素之间使用逗号分隔，元素形式为“键:值”，其中“键”不允许重复并且必须为不可变类型，“值”可以是任意类型的数据。例：{'a':97, 'b':98, 'c':99}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*集合类型（set）所有元素放在一对大括号中，元素之间使用逗号分隔，元素不允许重复且必须为不可变类型。 例：{'bread', 'beer', 'orange'}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "问：以上四种类型的下标有什么区别？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建列表对象\n",
    "x_list = [1, 2, 3]\n",
    "# 创建元组对象\n",
    "x_tuple = (1, 2, 3)\n",
    "# 创建字典对象，元素形式为“键:值”\n",
    "x_dict = {'a':97, 'b':98, 'c':99}\n",
    "# 创建集合对象\n",
    "x_set = {1, 2, 3}\n",
    "# 使用下标访问列表中指定位置的元素，元素下标从0开始\n",
    "print(x_list[1])\n",
    "# 元组也支持使用序号作为下标，1表示第二个元素的下标\n",
    "print(x_tuple[1])\n",
    "# 访问字典中特定“键”对应的“值”，字典对象的下标是“键”\n",
    "print(x_dict['a'])\n",
    "# 查看列表长度，也就是其中元素的个数\n",
    "print(len(x_list))\n",
    "# 查看元素2在元组中首次出现的位置\n",
    "print(x_tuple.index(2))\n",
    "# 查看字典中哪些“键”对应的“值”为98\n",
    "for key, value in x_dict.items():\n",
    "    if value == 98:\n",
    "        print(key)\n",
    "# 查看集合中元素的最大值\n",
    "print(max(x_set))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （3）列表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ① 创建列表\n",
    "除了用方括号直接创建列表之外，还可以使用list()函数把元组、range对象、字符串、字典、集合以及map对象、zip对象、enumerate对象等类似对象转换为列表。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list((3, 5, 7, 9, 11))       # 将元组转换为列表\n",
    "[3, 5, 7, 9, 11]\n",
    "list(range(1, 10, 2))        # 将range对象转换为列表\n",
    "[1, 3, 5, 7, 9]\n",
    "list(map(str, range(10)))    # 将map对象转换为列表\n",
    "['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']\n",
    "list(zip('abcd', [1,2,3,4])) # 将zip对象转换为列表\n",
    "[('a', 1), ('b', 2), ('c', 3), ('d', 4)]\n",
    "list(enumerate('Python'))    # 将enumerate对象转换为列表\n",
    "[(0, 'P'), (1, 'y'), (2, 't'), (3, 'h'), (4, 'o'), (5, 'n')]\n",
    "list(filter(str.isdigit, 'a1b2c3d456')) # 将filter对象转换为列表\n",
    "['1', '2', '3', '4', '5', '6']\n",
    "list('hello world')          # 将字符串转换为列表，每个字符转换为列中的一个元素\n",
    "['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']\n",
    "list({3, 7, 5})              # 将集合转换为列表，集合中的元素是无序的\n",
    "[3, 5, 7]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ② 访问列表\n",
    "使用下标访问列表中的元素，列表、元组、字符串都支持双向索引。正向索引：0，1，2……，反向索引：-1，-2，-3……"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = list(range(10))\n",
    "print(data)\n",
    "print(data[0])              # 第一个元素的下标为0\n",
    "print(data[1])              # 第二个元素的下标为1\n",
    "print(data[-1])             # -1表示最后一个元素的下标\n",
    "print(data[15])             # 15不是有效下标，代码抛出异常"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ③ 列表常用方法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "append()、insert()、extend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# append() 用于向列表尾部追加一个元素，不影响列表中已有元素的位置\n",
    "# insert() 用于向列表任意指定位置插入一个元素，该位置之后的所有元素自动向后移动，下标加1\n",
    "# extend() 用于将另一个列表中的所有元素追加至当前列表的尾部\n",
    "lst = [1, 2, 3, 4]\n",
    "lst.append(5)\n",
    "lst.insert(0, 0)\n",
    "lst.insert(2, 1.5)\n",
    "lst.extend([6, 7])\n",
    "print(lst)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pop()、remove()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# pop() 用于删除并返回列表中指定位置上的元素，不指定位置时默认是列表中最后一个元素，如果列表为空或指定位置不存在则报错\n",
    "# remove() 用于删除列表中第一个与指定值相等的元素，如果列表中不存在该指定值则报错\n",
    "lst = [1, 2, 3, 4, 5, 6]\n",
    "print(lst.pop())            # 删除并返回最后一个元素\n",
    "print(lst.pop(0))           # 删除并返回下标为0的元素，后面的元素向前移动\n",
    "print(lst.pop(2))           # 删除并返回下标为2的元素，后面的元素向前移动\n",
    "print(lst)\n",
    "lst = [1, 2, 3, 2, 4, 2]\n",
    "lst.remove(2)               # 删除第一个2，该方法没有返回值\n",
    "print(lst)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "count()、index()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# count() 用于返回列表中指定元素出现的次数\n",
    "# index() 用于返回指定元素在列表中首次出现的位置，如果列表中不存在该指定元素，则报错\n",
    "lst = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]\n",
    "print(lst.count(2))       # 输出2\n",
    "print(lst.index(4))       # 输出6\n",
    "print(lst.index(5))       # 代码抛出异常，提示5 is not in list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "sort()、reverse()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# sort()    用于按指定的规则对列表中所有元素进行排序\n",
    "# reverse() 用于翻转列表中的所有元素，首尾交换\n",
    "from random import sample\n",
    "\n",
    "# 在range(10000)中任选10个不重复的随机数\n",
    "data = sample(range(10000), 10)\n",
    "print(data)\n",
    "data.reverse()             # 翻转，首尾交换，该方法没有返回值\n",
    "print(data)\n",
    "data.sort()                # 按元素大小进行排序，该方法没有返回值\n",
    "print(data)\n",
    "data.sort(key=str)         # 按所有元素转换为字符串后的大小进行排序\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ④ 列表推导式\n",
    "列表推导式在逻辑上等价于一个循环语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data1 = [2**i for i in range(5)]\n",
    "等价于\n",
    "data1 = []\n",
    "for i in range(5):\n",
    "    data1.append(2**i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data2 = [num for num in range(20) if num%2==1]\n",
    "等价于\n",
    "data2 = []\n",
    "for num in range(20):\n",
    "    if num%2 == 1:\n",
    "        data.append(num)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data3 = [(x,y) for x in range(3) for y in range(2)]\n",
    "等价于\n",
    "data3 = []\n",
    "for x in range(3):\n",
    "    for y in range(2):\n",
    "        data3.append((x,y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ⑤ 列表切片\n",
    "切片是用来获取列表、元组、字符串等有序序列中部分元素的一种语法，语法格式[start:end:step]----- start表示开始位置，默认为0；end表示截止位置（但不包含）默认为列表长度；step表示切片的步长，默认为1，如果step为负整数，则表示反向切片。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = list(range(10))\n",
    "print(data[:])          # 获取所有元素的副本\n",
    "print(data[:3])         # 前三个元素\n",
    "print(data[3:])         # 下标3之后的所有元素\n",
    "print(data[::3])        # 每3个元素选取1个\n",
    "print(data[-3:])        # 最后3个元素\n",
    "print(data[:-5])        # 除最后5个元素之外的所有元素"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （4）元组\n",
    "除了用圆括号直接创建元组之外，还可以使用tuple()函数把列表、range对象、字符串、字典、集合以及map对象、zip对象等类似对象转换为元组。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "元组和列表的区别："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "~元组是不可变的，不能直接修改元组中元素的值，也不能为元组增加或删除元素。因此，元组没有提供append()、extend()和insert()等方法，也没有remove()和pop()方法。但是元组可以进行连接组合"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "~元组的访问速度比列表更快，开销更小。如果定义了一系列常量值，主要用途只是对它们进行遍历或其他类似操作，那么一般建议使用元组而不用列表。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "~元组可以使得代码更加安全。例如，调用函数时使用元组传递参数可以防止在函数中修改元组，而使用列表则无法保证这一点。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "~元组可用作字典的键，也可以作为集合的元素，但列表不可以，包含列表的元组也不可以。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tuple_one = (1,2)\n",
    "tuple_two = ('abc','xyz')\n",
    "tuple_three = tuple_one + tuple_two\n",
    "tuple_three"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （5）字典\n",
    "  字典中每个元素包含“键”和“值”两部分。python中“键”可以是任意不可变数据，例如整数、浮点数、复数、字符串、元组等，但不可以是列表、集合、字典或其他可变类型，且字典中的“键”不允许重复，“值”可以重复。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ① 字典的创建\n",
    "除了用大括号创建字典之外，还可以使用dict类的不同形式创建。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = dict(name='张三', age=18, sex='M')\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = dict.fromkeys([1, 2, 3, 4])    # 以指定的数据为“键”，“值”为空\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ② 字典的访问\n",
    "把“键”作为下标可以返回对应的值，如果键不存在，则报错；get()方法用于获取指定“键”对应的“值”，如果键不存在，则返回空值或者指定的值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = dict(name='张三', age=18, sex='M')\n",
    "print(data['name'])                         # 使用“键”作为下标，访问“值”\n",
    "print(data.get('age'))\n",
    "print(data.get('address', '不存在这个键'))   # “键”不存在，返回默认值\n",
    "print(list(data))                           # 把所有的“键”转换为列表\n",
    "print(list(data.values()))                  # 把所有的“值”转换为列表\n",
    "print(list(data.items()))                   # 把所有的元素转换为列表\n",
    "for key, value in data.items():             # 遍历字典的“键：值”元素\n",
    "    print(key, value, sep='\\t')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ③ 字典元素的修改、添加、删除"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 当以指定“键”为下标为字典元素赋值时，有两种含义：\n",
    "# 1）若该“键”存在，表示修改该“键”对应的值；\n",
    "# 2）若不存在，表示添加一个新元素。\n",
    "sock = {'IP': '127.0.0.1', 'port': 80}\n",
    "sock['port'] = 8080                  # 修改已有元素的“值”\n",
    "sock['protocol'] = 'TCP'             # 增加新元素\n",
    "print(sock)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用字典对象的update()方法可以将另一个字典的元素一次性全部添加到当前字典对象。\n",
    "# 如果两个字典中存在相同的“键”，则以另一个字典中的“值”为准对当前字典进行更新。\n",
    "sock = {'IP': '127.0.0.1', 'port': 80}\n",
    "# 更新了一个元素的“值”，增加了一个新元素\n",
    "sock.update({'IP':'192.168.9.62', 'protocol':'TCP'})\n",
    "print(sock)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 可以使用字典对象的pop()删除指定“键”对应的元素，同时返回对应的“值”。\n",
    "# 另外，也可以使用del删除指定的“键”对应的元素。\n",
    "sock = {'IP': '192.168.9.62', 'port': 80, 'protocol': 'TCP'}\n",
    "print(sock.pop('IP'))           # 删除并返回指定“键”的元素\n",
    "del sock['port']                # 删除指定“键”的元素\n",
    "print(sock)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （6）集合"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "~集合中只能包含数字、字符串、元组等不可变类型的数据，而不能包含列表、字典、集合等可变类型的数据，包含列表等可变类型数据的元组也不能作为集合的元素。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "~集合中的元素是无序的，元素存储顺序和添加顺序并不一致。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "~集合不支持使用下标直接访问特定位置上的元素，也不支持使用random中的choice()函数从集合中随机选取元素，但支持使用random模块中的sample()函数随机选取部分元素。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ① 集合常用方法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "add()、update()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# add()    用来增加新元素，如果该元素已存在，则忽略操作，不会报错\n",
    "# update() 用来合并另外一个集合中的元素到当前集合中，并自动去除重复元素\n",
    "data = {30, 40, 50}\n",
    "data.add(20)               # 增加新元素20\n",
    "data.add(50)               # 集合中已包含50，忽略本次操作\n",
    "data.update({40, 60})      # 忽略40，增加新元素60\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pop()、remove()、discard()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# pop()    用来随机删除并返回集合中的一个元素，如果集合为空则报错\n",
    "# remove()  用来删除集合中的指定元素，如果指定元素不存在，则报错\n",
    "# discard() 用来删除集合中的指定元素，如果指定元素不存在，则直接忽略\n",
    "data = {30, 40, 50}\n",
    "data.remove(30)          # 删除元素30\n",
    "data.discard(30)         # 集合中没有30，忽略本次操作\n",
    "print(data.pop())        # 删除并返回集合中的一个元素\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.运算符\n",
    "查阅P14-15页表2-2常用Python运算符"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （1）算术运算符\n",
    "+运算符除了用于算术加法以外，还可以用于列表、元组、字符串的连接。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(3 + 5)\n",
    "print(3.4 + 4.5)\n",
    "print((3+4j) + (5+6j))\n",
    "print('abc' + 'def')\n",
    "print([1,2] + [3,4])\n",
    "print((1,2) + (3,))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-运算符除了用于整数、浮点数、复数之间的算术减法和相反数之外，还可以计算集合的差集。需要注意的是，在进行浮点数之间的运算时，有可能会出现误差。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(7.9 - 4.5)                    # 注意，结果有误差\n",
    "print(5 - 3)\n",
    "num = 3\n",
    "print(-num)\n",
    "print(--num)                        # 注意，这里的--是两个负号，负负得正\n",
    "print(-(-num))                      # 与上一行代码含义相同\n",
    "print({1,2,3} - {3,4,5})            # 计算差集，差集指的是，当集合A、B相减，集合A中不属于集合B的元素叫做A与B的差集\n",
    "print({3,4,5} - {1,2,3})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*运算符除了表示整数、浮点数、复数之间的算术乘法，还可用于列表、元组、字符串这几个类型的对象与整数的乘法，表示序列元素的重复，生成新的列表、元组或字符串。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(3 * 5)\n",
    "print((3+4j) * (5+6j))\n",
    "print('重要的事情说三遍！' * 3)\n",
    "print([0] * 5)\n",
    "print((0,) * 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运算符/和//\n",
    "在Python中分别表示真除法和求整商。在使用时，要特别注意整除运算符//“向下取整”的特点。例如，-17 / 4的结果是-4.25，在数轴上小于-4.25的最大整数是-5，所以-17 // 4的结果是-5。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(17 / 4)\n",
    "print(17 // 4)\n",
    "print((-17) / 4)\n",
    "print((-17) // 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "%运算符可以用于求余数运算，还可以用于字符串格式化。在计算余数时，结果与%右侧的运算数符号一致。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(365 % 7)\n",
    "print(365 % 2)\n",
    "print('%c,%c, %c' % (65, 97, 48))   # 把65、97、48格式化为字符"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**运算符表示幂运算。使用时应注意，该运算符具有右结合性，也就是说，如果有两个连续的**运算符，那么先计算右边的再计算左边的，除非使用圆括号明确修改表达式的计算顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(2 ** 4)\n",
    "print(3 ** 3 ** 3)\n",
    "print(3 ** (3**3))           # 与上一行代码含义相同\n",
    "print((3**3) ** 3)           # 使用圆括号修改计算顺序\n",
    "print(9 ** 0.5)              # 计算9的平方根\n",
    "print((-1) ** 0.5)           # 对复数计算平方根得到复数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （2）关系运算符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(3+2 < 7+8)                          # 关系运算符优先级低于算术运算符\n",
    "print(3 < 5 > 2)                          # 等价于3<5 and 5>2\n",
    "print(3 == 3 < 5)                         # 等价于3==3 and 3<5\n",
    "print('12345' > '23456')                  # 第一个字符'1'<'2'，直接得出结论\n",
    "print('abcd' > 'Abcd')                    # 第一个字符'a'>'A'，直接得出结论\n",
    "print([85, 92, 73, 84] < [91, 82, 73])    # 第一个数字85<91，直接得出结论\n",
    "print([180, 90, 101] > [180, 90, 99])     # 前两个数字相等，第三个数字101>99\n",
    "print({1, 2, 3, 4} > {3, 4, 5})           # 第一个集合不是第二个集合的超集\n",
    "print({1, 2, 3, 4} <= {3, 4, 5})          # 第一个集合不是第二个集合的子集\n",
    "print([1, 2, 3, 4] > [1, 2, 3])           # 前三个元素相等\n",
    "                                          # 并且第一个列表有多余的元素"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （3）成员测试运算符\n",
    "成员测试运算符in用于测试一个对象是否包含另一个对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(60 in [70, 60, 50, 80])\n",
    "print('abc' in 'a1b2c3dfg')\n",
    "print([3] in [[3], [4], [5]])\n",
    "print('3' in map(str, range(5)))\n",
    "print(5 in range(5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### （4）集合运算符\n",
    "集合的交集、并集、差集、对称差集分别用&、|、-、^运算符来实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "A = {35, 45, 55, 65, 75}\n",
    "B = {65, 75, 85, 95}\n",
    "print(A | B)\n",
    "print(A & B)\n",
    "print(A - B)\n",
    "print(B - A)\n",
    "print(A ^ B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
